//
// Created by baka on 2025/10/19.
//



#include "webserver.h"

#include "beep.h"
#include "cmsis_os.h"
#include "dhcp.h"
#include "fatfs.h"
#include "httpPacket.h"
#include "LED.h"
#include "lwip.h"
#include "protocol.h"
#include "uart_printf.h"
#include "lwip/sockets.h"
#include "string.h"



osThreadId WebServerTskHandle;
osThreadId WebServerThreadTskHandle;
osMutexId webServerMutexHandle;
osMessageQId readHandle;




#define WEBSERVER_BUFSIZE 1600
char dataRecv[WEBSERVER_BUFSIZE];
char dataSend[WEBSERVER_BUFSIZE];
http_packet_t readPacket;
http_packet_t respondPacket;


/*************函数声明*****************/
void WebServerTask(void const * argument);
void vHttpServerTask();
uint8_t http_data_recv(int cfd);
uint8_t http_data_process(int cfd);
uint8_t http_data_send(int cfd);
/*************函数声明*****************/


/*************webserver初始化*****************/
void webserver_init(void)
{
    osThreadDef(WebServerTask, WebServerTask, osPriorityRealtime, 0, 1024*2);
    WebServerTskHandle = osThreadCreate(osThread(WebServerTask), NULL);
    osMutexDef(webServerMutexHandle);
    webServerMutexHandle = osMutexCreate(osMutex(webServerMutexHandle));
}
/*************webserver初始化*****************/


/*************创建服务端task*****************/
void WebServerTask(void const * argument)
{
    osDelay(1000);
    serverControl serverCtl;
    serverControl_init(&serverCtl);
    MX_LWIP_Init();
    MX_FATFS_Init();
    for(;;)
    {
        server_state_transition(&serverCtl);
        osDelay(10);
    }
}
/*************创建服务端task*****************/



/**** serverControl 初始化
 *
 *返回值    成功返回True  失败返回False
 ****/
bool serverControl_init(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl init failed %p",serverControl);
        return false;
    }
    //设置服务器初始状态
    memset(serverControl, 0, sizeof(*serverControl));
    serverControl->nextParseState = PARSE_WAIT;
    serverControl->nextState = SERVER_START;

    //设置服务器相关的结构体
    serverControl->server.sin_family = AF_INET;
    serverControl->server.sin_port = htons(80);
    serverControl->server.sin_addr.s_addr = 0;

    serverControl->maxRecvSize = WEBSERVER_BUFSIZE;
    serverControl->maxSendSize = WEBSERVER_BUFSIZE;

    serverControl->recvpacket.http_packet = dataRecv;
    serverControl->sendpacket.http_packet = dataSend;
    P_DEBUG("serverControl init success");
    return true;
}

/**** 创建socket描述符
 *
 *
 ****/
void user_create_socket(serverControl *serverControl)
{
    if (serverControl == NULL) {
        return;
    }
    serverControl->sfd = socket(AF_INET, SOCK_STREAM, 0);
    if (serverControl->sfd < 0)
    {
        const int err = errno; // 获取错误码
        ERROR("bind failed, error code: %d\n", err);
        ERROR("Error description: %s\n", strerror(err));
        //套接字创建失败
        ERROR("user_create_socket failed : %d", serverControl->sfd);
        serverControl->nextState = SERVER_START;
    }

    // 设置socket选项    SO_REUSEADDR：允许本地地址重用   默认不开启  需要定义 #define SO_REUSE 1
     const int optVal = 1;
    const socklen_t optValSize = sizeof(optVal);
    // if (lwip_setsockopt(serverControl->sfd, SOL_SOCKET, SO_REUSEADDR, &optVal, optValSize)< 0)
    // {
    //     const int err = errno; // 获取错误码
    //     ERROR("setsockopt failed, error code: %d\n", err);
    //     ERROR("Error description: %s\n", strerror(err));
    //     close(serverControl->sfd); // 关闭socket
    //     serverControl->nextState = SERVER_START;
    //     return;
    // }

    //套接字创建成功
    serverControl->nextState = SERVER_BIND;
    P_DEBUG("user_create_socket success");
}


/****
 *
 *服务端绑定ip和端口
 ****/
void user_bind(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    if (serverControl->sfd < 0)
    {
        serverControl->nextState = SERVER_ERROR;
        return;
    }
    const int8_t ret = bind(serverControl->sfd,(struct sockaddr *)&serverControl->server,sizeof(serverControl->server));
    if (ret < 0)
    {
        const int err = errno; // 获取错误码
        ERROR("bind failed, error code: %d\n", err);
        ERROR("Error description: %s\n", strerror(err));
        serverControl->nextState = SERVER_BIND;
        return;
    }
    serverControl->nextState = SERVER_LISTEN;
    P_DEBUG("user_bind success");
}




/****
 *
 *服务端开启监听
 ****/
void user_listen(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    if (serverControl->sfd < 0)
    {
        serverControl->nextState = SERVER_ERROR;
        return;
    }
    const int8_t ret = listen(serverControl->sfd,MEMP_NUM_NETCONN - 1);
    if (ret < 0)
    {
        const int err = errno; // 获取错误码
        ERROR("user_listen failed, error code: %d\n", err);
        ERROR("user_listen description: %s\n", strerror(err));
        ERROR("user_listen failed : %d", ret);
        serverControl->nextState = SERVER_ERROR;
        return;
    }
    serverControl->nextState = SERVER_ACCEPT;
    P_DEBUG("user_listen success");
}



/****
 *
 *接受客户端连接
 ****/
void user_accept(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    if (serverControl->sfd < 0)
    {
        // const int err = errno; // 获取错误码
        // ERROR("user_accept failed, error code: %d\n", err);
        // ERROR("user_accept description: %s\n", strerror(err));
        // ERROR("user_accept failed serverControl->sfd : %d", serverControl->sfd);
    }
    socklen_t client = sizeof(serverControl->client);
    serverControl->cfd = accept(serverControl->sfd,
        (struct sockaddr *)&serverControl->client,
        &client);
    if (serverControl->cfd  < 0)
    {
        const int err = errno; // 获取错误码
        ERROR("user_accept failed, error code: %d\n", err);
        ERROR("user_accept description: %s\n", strerror(err));
        ERROR("user_accept failed : %d", serverControl->cfd);
        // serverControl->nextState = SERVER_ERROR;  //直接重启服务会存在端口重用 导致无法重启服务成功
        close(serverControl->cfd);
        serverControl->nextState  = SERVER_ACCEPT;
        return;
    }
    serverControl->nextState = SERVER_RECV_DATA;
    P_DEBUG("user_accept success");
}



/****
 *
 *读数据
 ****/
void user_read(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    if (serverControl->cfd < 0)
    {
        const int err = errno; // 获取错误码
        ERROR("user_read failed, error code: %d\n", err);
        ERROR("Error description: %s\n", strerror(err));
        serverControl->nextState = SERVER_NORMAL_ERROR;
        ERROR("user_read failed serverControl->cfd : %d", serverControl->cfd);
        return;
    }
    memset(dataRecv, 0, sizeof(dataRecv));
    memset(dataSend, 0, sizeof(dataSend));
    memset(&serverControl->recvpacket, 0, sizeof(serverControl->recvpacket));
    memset(&serverControl->sendpacket, 0, sizeof(serverControl->sendpacket));
    const int recvSize = read(serverControl->cfd, dataRecv, WEBSERVER_BUFSIZE);
    if (recvSize < 0) //读失败
    {
        const int err = errno; // 获取错误码
        ERROR("user_read failed, error code: %d\n", err);
        ERROR("Error description: %s\n", strerror(err));
        ERROR("user_read failed : %d", dataRecv);
        //socket 内部错误  需要尝试重启服务端，甚至初始化lwip或者重启设备
        serverControl->nextState = SERVER_ERROR;
        return;
    }
    if(recvSize == 0){
        //远程断开连接状态，需要关闭cfd
        P_DEBUG("user_read client close connection:%d",serverControl->cfd);
        close(serverControl->cfd);
        serverControl->nextState = SERVER_ACCEPT;
        return;
    }


    //代码到这里说明，正确读到数据
    // P_DEBUG("data->\r\n%s",dataRecv);
    serverControl->recvSize = recvSize;
    serverControl->recvpacket.http_packet = dataRecv;
    serverControl->nextState = SERVER_SEND_DATA;
    P_DEBUG("user_read success");
}





/****
 *
 *发送数据
 ****/
void user_send(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    // INFO("data->%s",dataRecv);
    while (serverControl->nextState == SERVER_SEND_DATA)
    {
        //状态不发生改变，再次循环执行解析数据和发送数据的任务
        //循环结束的条件为 serverControl->nextState ！= SERVER_SEND_DATA
        parse_state_transition(serverControl);
    }
}




/****
 *
 *分割字符串,分割头部和消息体  以\r\n\r\n作为分隔符
 ****/
void user_split_str_body(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    serverControl->recvpacket.http_packet_body =
        strstr(serverControl->recvpacket.http_packet, "\r\n\r\n");

    if (serverControl->recvpacket.http_packet_body == NULL)
    {
        //没有找到可以分割的数据，直接推出循环，关闭客户端的连接
        //再次等待下一次的连接
        ERROR("split body and header failed , wait new client ...");
        close(serverControl->cfd);
        serverControl->nextState = SERVER_ACCEPT;
        return;
    }
    *serverControl->recvpacket.http_packet_body = 0;
    serverControl->recvpacket.http_packet_body += 4;
    serverControl->nextParseState = PARSE_SPLIT_HEADER;
}


/****
 *
 *分割字符串,分割头部和请求行  以\r\n作为分隔符
 ****/
void user_split_str_header(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    serverControl->recvpacket.http_packet_headers =
        strstr(serverControl->recvpacket.http_packet, "\r\n");

    if (serverControl->recvpacket.http_packet_headers == NULL)
    {
        //没有找到可以分割的数据，直接推出循环，关闭客户端的连接
        //再次等待下一次的连接
        ERROR("split body and line failed , wait new client ...");
        close(serverControl->cfd);
        serverControl->nextState = SERVER_ACCEPT;
        return;
    }
    *serverControl->recvpacket.http_packet_headers = 0;
    serverControl->recvpacket.http_packet_headers += 2;
    serverControl->recvpacket.http_packet_lines = serverControl->recvpacket.http_packet;
    serverControl->nextParseState = PARSE_LINE;
}




/****
 *
 *line
 ****/
void user_parse_line(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    char *Ptr = NULL;
    Ptr = strstr(serverControl->recvpacket.http_packet_lines, " ");
    if (Ptr == NULL)
    {
        ERROR("split method-url failed , wait new client ...");
        close(serverControl->cfd);
        serverControl->nextState = SERVER_ACCEPT;
        return;
    }
    *Ptr = 0;
    Ptr++;
    serverControl->recvpacket.lines[0].value = serverControl->recvpacket.http_packet_lines;
    serverControl->recvpacket.lines[1].value = Ptr;
    Ptr = NULL;
    Ptr = strstr(serverControl->recvpacket.lines[1].value, " ");
    if (Ptr == NULL)
    {
        ERROR("split url-http version failed , wait new client ...");
        close(serverControl->cfd);
        serverControl->nextState = SERVER_ACCEPT;
        return;
    }
    *Ptr = 0;
    Ptr++;
    serverControl->recvpacket.lines[2].value = Ptr;
    Ptr = NULL;
    Ptr = strstr(serverControl->recvpacket.lines[1].value, "?");
    if (Ptr != NULL)
    {
        *Ptr = 0;
        Ptr++;
        serverControl->recvpacket.http_packet_line_param = Ptr;
        Ptr = NULL;
    }
    if (strcmp(serverControl->recvpacket.lines[1].value, "/") == 0)
    {
        //设置默认路径为index.html
        serverControl->recvpacket.lines[1].value = "/index.html";
    }

    serverControl->nextParseState = PARSE_HEADER;
}



/****
 *
 *header
 ****/
void user_parse_header(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    //暂时不处理头部字段



    serverControl->nextParseState = PARSE_BODY;
}



/****
 *
 *
 ****/
void user_parse_body(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    //暂时不处理body


    if (strcmp(serverControl->recvpacket.lines[0].value,"GET") == 0)
    {
        serverControl->nextParseState = PARSE_GET;
    }
    else if (strcmp(serverControl->recvpacket.lines[0].value,"POST") == 0)
    {
        serverControl->nextParseState = PARSE_POST;
    }

}


int  fill_line_data(const serverControl *serverControl)
{
    const int ret = snprintf(serverControl->sendpacket.http_packet,
        serverControl->maxSendSize,
            "%s %s %s\r\n",
            serverControl->sendpacket.lines[0].value,
            serverControl->sendpacket.lines[1].value,
            serverControl->sendpacket.lines[2].value);
   return ret;
}

int  fill_send_header_data(serverControl *serverControl)
{
    const char* fileType = get_fileType(serverControl->recvpacket.lines[1].value);
    if (fileType == NULL)
    {
        P_DEBUG("fileType is null");
        return -1;
    }
    P_DEBUG("fill_send_header_data fileType:%s",fileType);
    P_DEBUG("fill_send_header_data Content-Length:%ld",serverControl->sendSize);
    serverControl->sendpacket.http_packet_length = strlen(serverControl->sendpacket.http_packet);
    const int ret = snprintf(serverControl->sendpacket.http_packet + serverControl->sendpacket.http_packet_length,
        serverControl->maxSendSize - serverControl->sendpacket.http_packet_length,
        "Content-Type: %s\r\nContent-Length: %ld\r\nConnection: close\r\nCache-Control: public, max-age=31536000\r\n\r\n",
        fileType,serverControl->sendSize);
    if (ret < 0)
    {
        ERROR("fill header data error");
        return ret;
    }

    const int n = write(serverControl->cfd,
        serverControl->sendpacket.http_packet,
        strlen(serverControl->sendpacket.http_packet));
    if (n < 0)
    {
        const int err = errno; // 获取错误码
        ERROR("fill_send_header_data send failed, error code: %d\n", err);
        ERROR("fill_send_header_data send description: %s\n", strerror(err));
        serverControl->nextState = SERVER_ERROR;
       return n;
    }




    return 0;
}


int  fill_send_body_body(serverControl *serverControl)
{
    int n = write(serverControl->cfd,
       dataSend,
        serverControl->sendpacket.bytes_read);
    if (n < 0)
    {
        const int err = errno; // 获取错误码
        ERROR("fill_send_body_body send failed, error code: %d\n", err);
        ERROR("fill_send_body_body send description: %s\n", strerror(err));
        serverControl->nextState = SERVER_ERROR;
        return n;
    }
    VERBOSE("write_body_body: %d",n);
    return 0;
}


/****
 *
 *
 ****/
void user_parse_get(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    memset(dataSend,0,sizeof(dataSend));
    memset(&serverControl->sendpacket,0,sizeof(serverControl->sendpacket));
    serverControl->sendpacket.http_packet = dataSend;
    serverControl->sendpacket.lines[0].value = "HTTP/1.1";
    serverControl->sendpacket.lines[1].value = "200";
    serverControl->sendpacket.lines[2].value = "OK";
    if (fill_line_data(serverControl) < 0)
    {
        //异常
        ERROR("fill_line_data error");
        close(serverControl->cfd);
        serverControl->nextState = SERVER_ACCEPT;
    }

    const FRESULT fp = f_open(&SDFile,serverControl->recvpacket.lines[1].value,FA_OPEN_EXISTING | FA_READ);
    if(fp != FR_OK)
    {
        ERROR("f_open failed:%s",serverControl->recvpacket.lines[1].value);
        switch(fp) {
        case FR_DISK_ERR:       printf("A hard error occurred in the low level disk I/O layer\n"); break;
        case FR_INT_ERR:        printf("Assertion failed\n"); break;
        case FR_NOT_READY:      printf("The physical drive cannot work\n"); break;
        case FR_NO_FILE:        printf("Could not find the file\n"); break;
        case FR_NO_PATH:        printf("Could not find the path\n");
            //判断是否为CMD字段的数据
            P_DEBUG("serverControl->recvpacket.http_packet_line_param : %s",
                serverControl->recvpacket.http_packet_line_param);
            if (strstr(serverControl->recvpacket.http_packet_line_param, "CMD") != 0)
            {
                serverControl->nextParseState = PARSE_CMD;
                // P_DEBUG("serverControl->nextParseState = PARSE_CMD;");
                // close(serverControl->cfd);
                f_close(&SDFile);
                return;
            }
            if (strstr(serverControl->recvpacket.http_packet_line_param, "DATA") != 0)
            {
                serverControl->nextParseState = PARSE_DATA;
                // P_DEBUG("serverControl->nextParseState = PARSE_CMD;");
                // close(serverControl->cfd);
                f_close(&SDFile);
                return;
            }
            break;
        case FR_INVALID_NAME:   printf("The path name format is invalid\n"); break;
        case FR_DENIED:         printf("Access denied due to prohibited access or directory full\n"); break;
        case FR_EXIST:          printf("Access denied due to prohibited access\n"); break;
        case FR_INVALID_OBJECT: printf("The file/directory object is invalid\n"); break;
        case FR_WRITE_PROTECTED:printf("The physical drive is write protected\n"); break;
        case FR_INVALID_DRIVE:  printf("The logical drive number is invalid\n"); break;
        case FR_NOT_ENABLED:    printf("The volume has no work area\n"); break;
        case FR_NO_FILESYSTEM:  printf("There is no valid FAT volume\n"); break;
        case FR_MKFS_ABORTED:   printf("The f_mkfs() aborted due to any problem\n"); break;
        case FR_TIMEOUT:        printf("Could not get a grant to access the volume within defined period\n"); break;
        case FR_LOCKED:         printf("The operation is rejected according to the file sharing policy\n"); break;
        case FR_NOT_ENOUGH_CORE:printf("LFN working buffer could not be allocated\n"); break;
        case FR_TOO_MANY_OPEN_FILES: printf("Number of open files > FF_FS_LOCK\n"); break;
        case FR_INVALID_PARAMETER:   printf("Given parameter is invalid\n"); break;
        default:                printf("Unknown error\n"); break;
        }
        close(serverControl->cfd);
        f_close(&SDFile);
        serverControl->nextState = SERVER_ACCEPT;
        return;
    }
    const uint32_t fSize = f_size(&SDFile);
    serverControl->sendSize = fSize;
    P_DEBUG("fSize:%ld",fSize);
    if (fill_send_header_data(serverControl) < 0)
    {
        ERROR("fill_send_header_data error");
        close(serverControl->cfd);
        f_close(&SDFile);
        serverControl->nextState = SERVER_ACCEPT;
        return;
    }

    //读文件
    memset(dataSend,0,sizeof(dataSend));
    UINT bytes_read;
    FRESULT result = f_read(&SDFile, dataSend, 1000, &bytes_read);
    if(result != FR_OK)
    {
        ERROR("f_read failed:%s",serverControl->recvpacket.lines[1].value);
        close(serverControl->cfd);
        f_close(&SDFile);
        serverControl->nextState = SERVER_ACCEPT;
        return;
    }
    do
    {
        serverControl->sendpacket.http_packet_body = dataSend;
        serverControl->sendpacket.bytes_read = bytes_read;
        if (fill_send_body_body(serverControl) < 0)
        {
            ERROR("fill_send_body_body error");
            close(serverControl->cfd);
            serverControl->nextState = SERVER_ACCEPT;
            return;
        }
        memset(dataSend,0,sizeof(dataSend));
        result = f_read(&SDFile, dataSend, 1000, &bytes_read);
         if(result != FR_OK)
        {
            ERROR("f_read failed:%s",serverControl->recvpacket.lines[1].value);
            close(serverControl->cfd);
            f_close(&SDFile);
            serverControl->nextState = SERVER_ACCEPT;
            return;
        }
    }while(bytes_read > 0);
    P_DEBUG("send sucessful:%s",serverControl->recvpacket.lines[1].value);
    f_close(&SDFile);
    //成功也好，失败也好，都结束
    close(serverControl->cfd);
    serverControl->nextState = SERVER_ACCEPT;

}

enum
{
    CMD_LED_ON,
    CMD_LED_OFF,
    CMD_BEEP_ON,
    CMD_BEEP_OFF,
    CMD_FAN_ON,
    CMD_FAN_OFF,
    CMD_LIGHT,
    CMD_TEM,
    CMD_HUM,
    CMD_MAX,
};
const char CMD_DATA[CMD_MAX][16]={
    {"LED_ON"},
    {"LED_OFF"},
    {"BEEP_ON"},
    {"BEEP_OFF"},
    {"FAN_ON"},
    {"FAN_OFF"},
    {"LIGHT"},
    {"TEM"},
    {"HUM"}
};

int find_cmd(serverControl *serverControl)
{
    int ret = -1;
    for (int i = 0;i < CMD_MAX; i++)
    {
        if (strstr(serverControl->recvpacket.http_packet_line_param, CMD_DATA[i]) != NULL)
        {
            ret = i;
            P_DEBUG("find_cmd cmd:%s",CMD_DATA[i]);
        }
    }
    return ret;
}


extern volatile uint32_t ADC_value;
extern Sensor_t sensor;
int cmd_action(int index)
{
    int ret = -1;
    LED_HandleTypeDef led = {.port = GPIOE, .pin = GPIO_PIN_2, .state = 1};
    if (index >= CMD_MAX || index < 0)
    {
        return -1;
    }
    switch (index)
    {
        case CMD_LED_ON:
            led.state = 1;
            xQueueSend(ledQueueHandle,&led, 0);
            ret = 0;
        break;
        case CMD_LED_OFF:
            led.state = 0;
            xQueueSend(ledQueueHandle,&led, 0);
            ret = 0;
        break;
        case CMD_BEEP_ON:
        beep_on();
        INFO("BEEP_ON++++++++++++++++++++++++++++++++++++++");
        ret = 0;
        break;
        case CMD_BEEP_OFF:
        beep_off();
        INFO("BEEP_OFF +++++++++++++++++++++++++++++++++++");
        ret = 0;
        break;
        case CMD_FAN_ON:
        INFO("FAN_ON+++++++++++++++++++++++++++++++");
        fan_control(1);
        ret = 0;
        break;
        case CMD_FAN_OFF:
        INFO("FAN_OFF+++++++++++++++++++++++++++++++");
        fan_control(0);
        ret = 0;
        break;
        case CMD_LIGHT:
        ret = ADC_value;
        break;
        case CMD_TEM:
        ret = sensor.TEM;
        break;
        case CMD_HUM:
        ret = sensor.HUM;
        break;
        default:
        break;
    }
    return ret;
}

void user_parse_cmd(serverControl *serverControl)
{
    //
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }


    int ret = find_cmd(serverControl);

    if (ret <= -1)
    {
        const char *buf = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nno found cmd";
        P_DEBUG("no found cmd");
        const int n = write(serverControl->cfd,
        buf,
        strlen(buf));
    }
    else if (ret <= CMD_FAN_OFF)
    {
        const char *buf = "HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nok";
        P_DEBUG("CMD:%s",CMD_DATA[ret]);
        const int n = write(serverControl->cfd,
        buf,
        strlen(buf));
        //执行对应命令
        cmd_action(ret);
    }
    else
    {
        P_DEBUG("CMD:%s",CMD_DATA[ret]);
        ret = cmd_action(ret);
        char numBuf[8] = {0};
        snprintf(numBuf, sizeof(numBuf), "%d", ret);
        char buf[128] = {0};
        snprintf(buf,sizeof(buf),
            "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%d",
            strlen(numBuf),ret);

        const int n = write(serverControl->cfd,
        buf,
        strlen(buf));
    }


    close(serverControl->cfd);
    serverControl->nextState = SERVER_ACCEPT;
}



void parse_state_transition(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    switch (serverControl->nextParseState)
    {
        case PARSE_WAIT:
        serverControl->nextParseState = PARSE_SPLIT_BODY;
        break;
        case PARSE_SPLIT_BODY:
            user_split_str_body(serverControl);
        break;
        case PARSE_SPLIT_HEADER:
        user_split_str_header(serverControl);
        break;
        case PARSE_LINE:
            user_parse_line(serverControl);
            if (serverControl->recvpacket.lines[0].value != NULL)
            {
                INFO("method:%s",serverControl->recvpacket.lines[0].value);
                INFO("url:%s",serverControl->recvpacket.lines[1].value);
                INFO("http_version:%s",serverControl->recvpacket.lines[2].value);
            }

        break;
        case PARSE_HEADER:
        user_parse_header(serverControl);
        break;
        case PARSE_BODY:
        user_parse_body(serverControl);
        break;
        case PARSE_GET:
        user_parse_get(serverControl);
        break;
        case PARSE_POST:

        break;

        case PARSE_ERROR:
        return;
        break;
        case PARSE_CMD:
        user_parse_cmd(serverControl);
        break;
        case PARSE_DATA:

        break;
        break;
        default:
        serverControl->nextParseState = PARSE_ERROR;
        break;
    }
}


void server_state_transition(serverControl *serverControl)
{
    // INFO("server_state_transition");
    switch (serverControl->nextState)
    {
        case SERVER_START:
        serverControl->nextState = SERVER_SOCKET;
        break;
        case SERVER_SOCKET:
        user_create_socket(serverControl);
        break;
        case SERVER_BIND:
        user_bind(serverControl);
        break;
        case SERVER_LISTEN:
        user_listen(serverControl);
        break;
        case SERVER_ACCEPT:
        user_accept(serverControl);
        break;
        case SERVER_RECV_DATA:
        user_read(serverControl);
        break;
        case SERVER_SEND_DATA:
        serverControl->nextParseState = PARSE_WAIT;
        user_send(serverControl);
        break;
        case SERVER_NORMAL_ERROR:
        user_read_error(serverControl);
        case SERVER_ERROR:
        user_error(serverControl);
        break;
        default:
        break;
    }
}


/****
 *
 *读错误   关闭cfd即可  之后重新等待新的连接
 ****/
void user_read_error(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    //判断有没有客户端socket描述符
    if (serverControl->cfd > -1)
    {
        P_DEBUG("user_read_error close connection:%d",serverControl->cfd);
        close(serverControl->cfd);
    }

    serverControl->nextState = SERVER_ACCEPT;
    P_DEBUG("user_read_error function success");
}





/****
 *
 *重大错误   需要重启服务端
 ****/
void user_error(serverControl *serverControl)
{
    if (serverControl == NULL)
    {
        ERROR("serverControl is null");
        return;
    }
    //存在问题  按照这个逻辑端口会被占用 需要修改   加tag
    //判断有没有服务端socket描述符
    if (serverControl->sfd > -1)
    {
        close(serverControl->sfd);
    }
    //判断有没有客户端socket描述符
    if (serverControl->cfd > -1)
    {
        close(serverControl->cfd);
    }


    serverControl->nextState = SERVER_START;
    P_DEBUG("restart server successful");
}



const char *get_fileType(const char *url) {
    // 获取最后一个'.'的位置
    const char *dot = strrchr(url, '.');
    if (!dot || dot == url) return "application/octet-stream";

    // 转换为小写比较
    if (strcasecmp(dot, ".html") == 0) return "text/html";
    if (strcasecmp(dot, ".htm") == 0) return "text/html";
    if (strcasecmp(dot, ".css") == 0) return "text/css";
    if (strcasecmp(dot, ".js") == 0) return "application/javascript";
    if (strcasecmp(dot, ".json") == 0) return "application/json";
    if (strcasecmp(dot, ".png") == 0) return "image/png";
    if (strcasecmp(dot, ".jpg") == 0 || strcasecmp(dot, ".jpeg") == 0) return "image/jpeg";
    if (strcasecmp(dot, ".gif") == 0) return "image/gif";
    if (strcasecmp(dot, ".ico") == 0) return "image/x-icon";
    if (strcasecmp(dot, ".svg") == 0) return "image/svg+xml";

    return "application/octet-stream";
}




